# build.py
import os
import shutil
import subprocess
import sys
import urllib.request
import py7zr

def download_snap7_dll():
    """下载 snap7.dll 文件"""

    snap7_url = "https://sourceforge.net/projects/snap7/files/1.4.2/snap7-full-1.4.2.7z/download"
    download_path = "snap7-full-1.4.2.7z"
    extract_dir = "snap7_temp"
    # win64_dll_path = "snap7-full-1.4.2\\release\\Windows\\Win64" # 此处调整路径，找到解压后到这个路径

    try:
        # 如果存在则不用重复下载
        if not os.path.exists(download_path):
            # 下载 snap7
            print("正在下载 snap7.dll...")
            urllib.request.urlretrieve(snap7_url, download_path)
            print("下载完成")
            
        # 创建解压目录
        os.makedirs(extract_dir, exist_ok=True)

        # 解压文件
        with py7zr.SevenZipFile(download_path, 'r') as z:
            z.extractall(extract_dir)
        print("解压完成")

        # 查找并复制 snap7.dll
        dll_found = False
        # for root, dirs, files in os.walk(extract_dir):
        #     if "snap7.dll" in files:
        #         # 此处调整路径
        #         # dll_path = os.path.join(root, "snap7.dll")
        #         dll_path = os.path.join(win64_dll_path, "snap7.dll")
        #         shutil.copy2(dll_path, "snap7.dll")
        #         print(f"找到并复制 snap7.dll: {dll_path}")
        #         dll_found = True
        #         break

        # 优先查找 Win64 目录
        win64_path = os.path.join(extract_dir, "snap7-full-1.4.2", "release", "Windows", "Win64")
        win64_dll_path = os.path.join(win64_path, "snap7.dll")

        if os.path.exists(win64_dll_path):
            shutil.copy2(win64_dll_path, "snap7.dll")
            print(f"找到并复制 snap7.dll: {win64_dll_path}")
            dll_found = True
        else:
            # 如果 Win64 目录不存在，尝试查找其他可能的目录
            possible_paths = [
                os.path.join(extract_dir, "release", "Windows", "Win64"),
                os.path.join(extract_dir, "release", "Windows", "Win32"),
                os.path.join(extract_dir, "bin", "x86_64-win"),
                os.path.join(extract_dir, "bin", "x86-win"),
                extract_dir  # 最后在整个解压目录中查找
            ]
            
            for path in possible_paths:
                dll_path = os.path.join(path, "snap7.dll")
                if os.path.exists(dll_path):
                    shutil.copy2(dll_path, "snap7.dll")
                    print(f"找到并复制 snap7.dll: {dll_path}")
                    dll_found = True
                    break
            
        if not dll_found:
            print("警告: 在下载的压缩包中未找到 snap7.dll")
            # 列出所有文件帮助调试
            print("压缩包内容:")
            for root, dirs, files in os.walk(extract_dir):
                for file in files:
                    print(f"  {os.path.join(root, file)}")
            return False
            
        # 清理临时文件
        shutil.rmtree(extract_dir)
        os.remove(download_path)
        
        return True
    except Exception as e:
        print(f"下载 snap7.dll 失败: {e}")
        # 清理可能的部分文件
        if os.path.exists(extract_dir):
            shutil.rmtree(extract_dir)
        return False

def ensure_log_directory():
    """确保日志目录存在并包含占位文件"""
    log_dir = "app/logs"
    if not os.path.exists(log_dir):
        os.makedirs(log_dir, exist_ok=True)
    
    # 创建占位文件
    placeholder_file = os.path.join(log_dir, ".keep")
    if not os.path.exists(placeholder_file):
        with open(placeholder_file, 'w') as f:
            f.write("This file ensures the logs directory is packaged")
        print("已创建日志目录占位文件")
    
def clean_build_folders():
    """清理构建文件夹"""
    folders_to_clean = ['build', 'dist']
    for folder in folders_to_clean:
        if os.path.exists(folder):
            print(f"清理 {folder} 文件夹...")
            shutil.rmtree(folder)

def copy_resources():
    """复制必要的资源文件到dist文件夹"""
    
    # 确保dist文件夹存在
    dist_path = 'dist/nx_path_planning'
    if not os.path.exists(dist_path):
        return
    
    # 复制配置文件夹
    if os.path.exists('app/data'):
        print("复制数据文件夹...")
        shutil.copytree('app/data', os.path.join(dist_path, 'app/data'), dirs_exist_ok=True)
    
    if os.path.exists('app/map_core/data'):
        print("复制配置文件夹...")
        shutil.copytree('app/map_core/data', os.path.join(dist_path, 'app/map_core/data'), dirs_exist_ok=True)

    if os.path.exists('app/logs'):
        print("复制日志文件夹...")
        shutil.copytree('app/logs', os.path.join(dist_path, 'app/logs'), dirs_exist_ok=True)

    if os.path.exists('static'):
        print("复制静态文件文件夹...")
        shutil.copytree('static', os.path.join(dist_path, '_internal/fastapi_offline/static'), dirs_exist_ok=True)

    # 复制 snap7.dll
    if os.path.exists('snap7.dll'):
        print("复制 snap7.dll 文件...")
        shutil.copy2('snap7.dll', os.path.join(dist_path, '_internal/snap7.dll'))

def build_executable():
    """使用PyInstaller构建可执行文件"""
    print("开始构建可执行文件...")
    
    # PyInstaller命令行参数
    pyinstaller_args = [
        'pyinstaller',
        '--name=nx_path_planning',
        '--noconfirm',  # 覆盖输出目录
        f'--add-data=app/data{os.pathsep}app/data',  # 添加配置文件夹
        f'--add-data=app/map_core/data{os.pathsep}app/map_core/data',
        f'--add-data=app/logs{os.pathsep}app/logs'
        '--hidden-import=snap7',  # 添加snap7模块'
    ]

    # 添加图标如果存在
    if os.path.exists('img/icon.ico'):
        pyinstaller_args.append('--icon=img/icon.ico')

    # 添加主程序入口
    pyinstaller_args.append('run.py')

    # 过滤掉空参数
    pyinstaller_args = [arg for arg in pyinstaller_args if arg]
    
    # 执行PyInstaller命令
    try:
        print(f"执行命令: {' '.join(pyinstaller_args)}")
        subprocess.run(pyinstaller_args, check=True)
        print("构建成功!")
    except subprocess.CalledProcessError as e:
        print(f"构建失败: {e}")
        return False
    
    return True

def main():
    # 确保当前工作目录是项目根目录
    os.chdir(os.path.dirname(os.path.abspath(__file__)))
    
    print("=== 开始打包 nx_path_planning 应用 ===")

    # 确保日志目录存在
    ensure_log_directory()

    # 检查并下载 snap7.dll 如果有snap7.dll文件，可以先手动复制到backend/下
    if not os.path.exists('snap7.dll'):
        if not download_snap7_dll():
            print("无法获取 snap7.dll，请手动下载并放置在项目根目录")
            print("下载地址: https://sourceforge.net/projects/snap7/files/")
            return
    
    # 清理旧的构建文件
    clean_build_folders()
    
    # 构建可执行文件
    if build_executable():
        # 复制额外资源
        copy_resources()
        print("\n打包完成! 可执行文件位于 dist/nx_path_planning 文件夹")
    else:
        print("\n打包失败!")

if __name__ == "__main__":
    main()